﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using MazeNet.Communication;

namespace NichosNotSoRandomKi
{
    public class NotSoRandomKI : PlayerBase
    {

        private Random _mRandom;
        public NotSoRandomKI()
        {
            _mRandom = new Random(12345);
        }

        /// <summary>
        /// Berechnet einen Spielzug auf Basis von Zufall.
        /// </summary>
        /// <param name="_uAwaitMoveMsg">Zug Aufforderung</param>
        /// <returns>Den Spielzug</returns>
        public override MoveMessageType CalculateMove(AwaitMoveMessageType _uAwaitMoveMsg)
        {
            #region LocalVars
            MoveMessageType _lRet = new MoveMessageType();
            Point _lPlayerPos;
            List<Move> _lPossibleMoves = GenerateMoves(_uAwaitMoveMsg.board);
            Dictionary<treasureType, Point> _lTreasures;
            bool _lRandomMove = true;
            #endregion

            //Jeder mögliche Zug wird durchprobiert
            foreach (Move _lMove in _lPossibleMoves)
            {
                //Wenn der aktuelle Schatz erreichbar ist, diesen Zug wählen
                _lPlayerPos = _lMove.Board.FindPlayer(_mID);
                _lTreasures = _lMove.Board.ReachableTreasures(_lPlayerPos);
                if (_lTreasures.ContainsKey(_uAwaitMoveMsg.treasure))
                {
                    _lPlayerPos = _lTreasures[_uAwaitMoveMsg.treasure];
                    _lRet = _lMove.GenerateMoveMessage(_lPlayerPos);
                    _lRandomMove = false;
                    break;
                }
            }

            //Wenn der Schatz nicht erreichbar ist Zufällig etwas machen
            if (_lRandomMove)
            {
                Move _lMove = TrollPlayer(_lPossibleMoves).ElementAt(0).Key;
                _lRet = _lMove.GenerateMoveMessage(ChooseRandomPosition(_lMove));
            }

            return _lRet;

        }

        private Dictionary<Move, int> TrollPlayer(List<Move> _uMoves)
        {
            Dictionary<int, Point> _lPlayerPos = null;
            Dictionary<Move, int> _lCompareMoves = new Dictionary<Move, int>();
            List<Move> _lSecondMoves;
            int _lReachableTreasures = 0;
            bool[,] _lReachableBuffer;

            foreach (Move m in _uMoves)
            {
                _lSecondMoves = GenerateMoves(m.Board);
                _lReachableTreasures = 0;
                _lReachableBuffer = new bool[7, 7]; 
                foreach (Move m2 in _lSecondMoves)
                {
                    _lPlayerPos = m2.Board.FindAllPlayers();
                    foreach (int i in _lPlayerPos.Keys)
                    {
                        if (i != _mID)
                        {
                            _lReachableBuffer = mergeReachable(_lReachableBuffer, m2.Board.ReachableFields(_lPlayerPos[i]));
                        }
                    }
                }
                _lReachableTreasures = countTrue(_lReachableBuffer);
                _lCompareMoves.Add(m, _lReachableTreasures);
            }
            _lCompareMoves.OrderBy(Move => Move.Value);
            return _lCompareMoves;
        }

        private Point ChooseRandomPosition(Move _uMove)
        {
            Random r = new Random();
            Point _lPlayerPos = _uMove.Board.FindPlayer(_mID);
            List<Point> _lReachable = _uMove.Board.ReachableFieldList(_lPlayerPos);
            int _lRandomReach = 0;
            bool[,] test = _uMove.Board.ReachableFields(_lPlayerPos);
            while (_lReachable.Count > 1 && _lRandomReach == 0)
            {
                _lRandomReach = r.Next(1, _lReachable.Count - 1);
            }
            _lPlayerPos = _lReachable[_lRandomReach];
            return _lPlayerPos;
        }


        private bool[,] mergeReachable(bool[,] first, bool[,] second)
        {
            bool[,] _lRet = new bool[7, 7];

            for (int i = 0; i < 7; ++i)
            {
                for (int j = 0; j < 7; ++j)
                {
                    _lRet[i, j] = first[i, j] || second[i, j];
                }
            }

            return _lRet;
        }

        private int countTrue(bool[,] toCount)
        {
            int i = 0;
            foreach (bool b in toCount)
            {
                if (b)
                    i++;
            }
            return i;
        }
    }
}
